[IA64] pal_halt_light emulatefor domU
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Thu, 24 Aug 2006 17:48:35 +0000 (11:48 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Thu, 24 Aug 2006 17:48:35 +0000 (11:48 -0600)
Signed-off-by: Atsushi SAKAI <sakaia@jp.fujitsu.com>
xen/arch/ia64/xen/domain.c
xen/arch/ia64/xen/hypercall.c
xen/include/asm-ia64/domain.h
xen/include/asm-ia64/vcpu.h

index 2130361cc37a94e73b243c36d67c9fb48d32e106..6f2a503f96a6cff803f4dc3e6898d3f4a52895c4 100644 (file)
@@ -239,6 +239,12 @@ void startup_cpu_idle_loop(void)
 # error "XMAPPEDREGS_SHIFT doesn't match sizeof(mapped_regs_t)."
 #endif
 
+void hlt_timer_fn(void *data)
+{
+       struct vcpu *v = data;
+       vcpu_unblock(v);
+}
+
 struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
 {
        struct vcpu *v;
@@ -298,6 +304,9 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
            v->arch.breakimm = d->arch.breakimm;
            v->arch.last_processor = INVALID_PROCESSOR;
        }
+       if (!VMX_DOMAIN(v)){
+               init_timer(&v->arch.hlt_timer, hlt_timer_fn, v, v->processor);
+       }
 
        return v;
 }
@@ -309,6 +318,7 @@ void relinquish_vcpu_resources(struct vcpu *v)
                            get_order_from_shift(XMAPPEDREGS_SHIFT));
         v->arch.privregs = NULL;
     }
+    kill_timer(&v->arch.hlt_timer);
 }
 
 void free_vcpu_struct(struct vcpu *v)
index b5321e030c53d4111161f43b6492b7056ef8490f..203d0211c56ebba285eb41d38d2ca26c04a4c79e 100644 (file)
@@ -235,7 +235,12 @@ fw_hypercall (struct pt_regs *regs)
                        }
                        else {
                                perfc_incrc(pal_halt_light);
-                               do_sched_op_compat(SCHEDOP_yield, 0);
+                               migrate_timer(&v->arch.hlt_timer,
+                                             v->processor);
+                               set_timer(&v->arch.hlt_timer,
+                                         vcpu_get_next_timer_ns(v));
+                               do_sched_op_compat(SCHEDOP_block, 0);
+                               stop_timer(&v->arch.hlt_timer);
                        }
                        regs->r8 = 0;
                        regs->r9 = 0;
index fed8c428e019bd815fe8fc3be6c8cd3af39aec84..394b3bc6ad6fc9fb4eb70c2927764757fd2bdc09 100644 (file)
@@ -198,6 +198,7 @@ struct arch_vcpu {
     unsigned long old_rsc;
     int mode_flags;
     fpswa_ret_t fpswa_ret;     /* save return values of FPSWA emulation */
+    struct timer hlt_timer;
     struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */
 
 #define INVALID_PROCESSOR       INT_MAX
index 87b3801b2f860721c69d42e51da1dd98fe54e88c..7bfc76f7615da65f1f42785612ce865c08c31e40 100644 (file)
@@ -4,6 +4,7 @@
 // TODO: Many (or perhaps most) of these should eventually be
 // static inline functions
 
+#include <asm/delay.h>
 #include <asm/fpu.h>
 #include <asm/tlb.h>
 #include <asm/ia64_int.h>
@@ -15,6 +16,7 @@ typedef       int BOOLEAN;
 struct vcpu;
 typedef        struct vcpu VCPU;
 typedef cpu_user_regs_t REGS;
+extern u64 cycle_to_ns(u64 cycle);
 
 /* Note: PSCB stands for Privilegied State Communication Block.  */
 #define VCPU(_v,_x)    (_v->arch.privregs->_x)
@@ -183,6 +185,21 @@ itir_mask(UINT64 itir)
     return (~((1UL << itir_ps(itir)) - 1));
 }
 
+static inline s64
+vcpu_get_next_timer_ns(VCPU *vcpu)
+{
+    s64 vcpu_get_next_timer_ns;
+    u64 d = PSCBX(vcpu, domain_itm);
+    u64 now = ia64_get_itc();
+
+    if (d > now)
+        vcpu_get_next_timer_ns = cycle_to_ns(d - now) + NOW();
+    else
+        vcpu_get_next_timer_ns = cycle_to_ns(local_cpu_data->itm_delta) + NOW();
+
+    return vcpu_get_next_timer_ns;
+}
+
 #define verbose(a...) do {if (vcpu_verbose) printf(a);} while(0)
 
 //#define vcpu_quick_region_check(_tr_regions,_ifa) 1